﻿using System;
using System.Collections.Generic;
using System.Net;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ArchitectingInnovation.PRISMvvM.Core.ServiceGateways
{
    

    public class ServiceQueue<T,TChannel> : IServiceQueue
        where T : ClientBase<TChannel>
        where TChannel : class

    {
        private readonly ClientBase<TChannel> _client;
        private readonly object _lock = new object();
        public ServiceQueue(T client)

        {
            this._client = client;
            this.ActionsInProgress = new List<Func<Object, IAsyncResult>>();
            this.QueuedActions = new Queue<Func<Object, IAsyncResult>>();
            
        }

        protected List<Func<Object, IAsyncResult>> ActionsInProgress { get; set; }

        protected Queue<Func<Object, IAsyncResult>> QueuedActions { get; set; }

        public void RegisterAction(Func<Object,IAsyncResult> action)
        {
           this.QueuedActions.Enqueue(action);
        }

        public void Execute()
        {
            lock (_lock)
            {
                if (QueuedActions.Count == 0)
                    return;
                Func<Object, IAsyncResult> a = null;
                while (QueuedActions.Count > 0)
                {
                    this.ActionsInProgress.Add(a);
                    a = QueuedActions.Dequeue();
                    var result = a(this);
                    System.Threading.ThreadPool.QueueUserWorkItem(x =>
                    {
                        result.AsyncWaitHandle.WaitOne();
                        OnDone(a);
                    });

                }
            }
        }

        protected void OnDone(Func<Object,IAsyncResult> action)
        {
            if(this.QueuedActions.Count == 0)
                this.CloseClient();
        }

        public void CancelPending()
        {
            foreach(var action in this.ActionsInProgress)
            {
                //TODO: cancel them.
            }
        }

        

        public void CancelAll()
        {
            this.QueuedActions.Clear();
            this.CancelPending();
            this.CloseClient();
        }

        protected void CloseClient()
        {
            _client.InnerChannel.Close();
            
        }



        
    }
}
